<?php
/**
 * @package account
 */
class Account extends DataExtension {
    private static $db = array(
        'Type' => 'Varchar(100)',
        'Date' => 'SS_Datetime',
        'Reference' => 'Varchar(100)',
        'Description' => 'Varchar(250)',
        'Debit' => 'Currency',
        'Credit' => 'Currency',
        'ForwardBalance' => 'Currency'
    );

    private static $has_one = array("Member" => 'Member');
    
    private static $default_sort = "Date DESC, ID DESC";
	
	private static $indexes = array(
        'Type' => true,
        'Date' => true,
        'Reference' => true
    );

    private static $searchable_fields = array(
        'Type',
        'Date' => array(
			'field' => 'DateField',
			'filter' => 'DateMatchFilter'
		),
        'Member.Username',
        'Member.FirstName',
        'Member.Surname',
        'Reference',
        'Description',
        'Debit' => array(
            'filter' => 'GreaterThanOrEqualFilter'
        ),
        'Credit' => array(
            'filter' => 'GreaterThanOrEqualFilter'
        )
    );

    private static $summary_fields = array(
        'Date.Nice',
        'Member.Username',
        'Member.Name',
        'Reference',
        'Description',
        'Debit',
        'Credit'
    );
    
    private static $casting = array(
        'Balance' => 'Currency',
        'TotalDebit' => 'Currency',
        'TotalCredit' => 'Currency'
    );

    private static $create_table_options = array('MySQLDatabase' => 'ENGINE=InnoDB');
    
    protected $member_id;
    
    public static function get($class, $memberid) {
        return $class::create()->setField('member_id', $memberid);
    }

    function getBalance() {
        $sql = "SELECT Balance FROM " . $this->owner->class . "Balance WHERE MemberID = " . $this->owner->member_id;
        return DB::query($sql)->value();
    }

    function getTotalDebit() {
        $sql = "SELECT TotalDebit FROM " . $this->owner->class . "Balance WHERE MemberID = " . $this->owner->member_id;
        return DB::query($sql)->value();
    }

    function getTotalCredit() {
        $sql = "SELECT TotalCredit FROM " . $this->owner->class . "Balance WHERE MemberID = " . $this->owner->member_id;
        return DB::query($sql)->value();
    }

    function augmentSQL(SQLQuery &$query) {

    }

    function augmentDatabase() {
        $options = Config::inst()->get($this->owner->class, 'create_table_options');
		$db = Config::inst()->get($this->owner->class, 'db');
        $fields = array(
            'Balance' => $db['ForwardBalance'],
            'TotalDebit' => $db['Debit'],
            'TotalCredit' => $db['Credit'],
            'MemberID' => 'Int'
        );
        $indexes = array('MemberID' => true);
        DB::requireTable($this->owner->class . "Balance", $fields, $indexes, false, $options);
    }

    function augmentWrite(&$manipulation) {
        $tables = array_keys($manipulation);
        $version_table = array();
        foreach($tables as $table) {
            $baseDataClass = ClassInfo::baseDataClass($table);

            $isRootClass = ($table == $baseDataClass);

            if($isRootClass) {
                if($manipulation[$table]['command'] == 'insert' || $manipulation[$table]['command'] == 'update') {
                    $memberid = $manipulation[$table]['fields']['MemberID'];
                    $debit = isset($manipulation[$table]['fields']['Debit']) ? $manipulation[$table]['fields']['Debit'] : 0;
                    $credit = isset($manipulation[$table]['fields']['Credit']) ? $manipulation[$table]['fields']['Credit'] : 0;
                    $cash_account = Account::get($this->owner->class, $memberid);
                    $balance = $cash_account->Balance + $credit - $debit;
                    $total_debit = $cash_account->TotalDebit + $debit;
                    $total_credit = $cash_account->TotalCredit + $credit;
                    $manipulation[$this->owner->class . "Balance"] = array(
                        'command' => 'update',
                        'fields' => array(
                            'Balance' => $balance,
                            'TotalDebit' => $total_debit,
                            'TotalCredit' => $total_credit,
                            'MemberID' => $memberid
                        ),
                        'where' => "MemberID = " . $memberid,
                    );
					$manipulation[$table]['fields']['ForwardBalance'] = $balance;

                    $date = isset($manipulation[$table]['fields']['Date']) ? $manipulation[$table]['fields']['Date'] : '';
                    if($date == '') {
                        $manipulation[$table]['fields']['Date'] = "'" . SS_Datetime::now()->Rfc2822() . "'";
                    }
                }
            }
        }
    }

	function updateFieldLabels(&$labels) {
		$labels['Type'] = _t('Account.TYPE', 'Type');
		$labels['Date'] = _t('Account.DATE', 'Date');
		$labels['Date.Nice'] = _t('Account.DATE', 'Date');
		$labels['Reference'] = _t('Account.REFERENCE', 'Reference');
		$labels['Description'] = _t('Account.DESCRIPTION', 'Description');
		$labels['Debit'] = _t('Account.DEBIT', 'Debit');
		$labels['Credit'] = _t('Account.CREDIT', 'Credit');
		$labels['ForwardBalance'] = _t('Account.ForwardBalance', 'Balance');
        $labels['Member.Username'] = _t('Account.USERNAME', 'Username');
		$labels['Member.Name'] = _t('Account.NAME', 'Name');
		$labels['Member.FirstName'] = _t('Account.FIRSTNAME', 'First Name');
		$labels['Member.Surname'] = _t('Account.SURNAME', 'Surname');
    }

    function validate(ValidationResult $validationResult) {
        if(!$this->owner->MemberID) {
            $subvalid = new ValidationResult();
            $subvalid->error(_t('Account.INVALID_MEMBER_ID', 'Invalid Member ID'), 'INVALID_MEMBER_ID');
            $validationResult->combineAnd($subvalid);
        }

        if($this->owner->Credit < 0 || $this->owner->Debit < 0 || ($this->owner->Credit <= 0 && $this->owner->Debit <= 0)) {
            $subvalid = new ValidationResult();
            $subvalid->error(_t('Account.INVALID_AMOUNT', 'Invalid Amount'), 'INVALID_AMOUNT');
            $validationResult->combineAnd($subvalid);
        }

        return $validationResult;
    }
	
	function getTypeByLang(){
		$class = sprintf('%sType', $this->owner->class);
		$type = $class::get_title_by_code($this->owner->Type);
		return $type ? $type : $this->Type;
	}

    function getAmountText(){
        if($this->owner->Credit > 0){
            return sprintf('%s(+)', DBField::create_field('Double', $this->owner->Credit)->Nice());
        }
        else{
            return sprintf('%s(-)', DBField::create_field('Double', $this->owner->Debit)->Nice());
        }
    }
}
?>
